#include <iostream>
#include <memory>
#include "AudioOutput.h"
#include "AVFrameQueue.h"
#include "DecodeThread.h"
#include "Log.h"
#include "DemuxThread.h"
#include "VideoOutput.h"

extern "C" {
#include <libavcodec/avcodec.h>
#include <libavutil/log.h>
}

int main(int argc, char **argv) {
    av_log_set_level(AV_LOG_INFO);
    // av_log_set_level(AV_LOG_VERBOSE);
    AVPacketQueue audio_packet_queue;
    AVPacketQueue video_packet_queue;
    AVFrameQueue audio_frame_queue;
    AVFrameQueue video_frame_queue;
    //解复用
    auto *demux_thread = new DemuxThread(&audio_packet_queue, &video_packet_queue);
    const char *video = "C:\\Users\\30654\\Videos\\2024-11-06 22-39-21.mkv";
    int ret = demux_thread->Init(video);
    if (ret < 0) {
        av_log(NULL, AV_LOG_ERROR, "DemuxThread::Init() failed\n");
        return -1;
    }
    ret = demux_thread->Start();
    if (ret < 0) {
        av_log(NULL, AV_LOG_ERROR, "DemuxThread::Start() failed\n");
        return -1;
    }
    // 解码线程
    auto *audio_decode_thread = new DecodeThread(&audio_packet_queue, &audio_frame_queue);
    ret = audio_decode_thread->Init(demux_thread->AudioCodecParameters());
    if (ret < 0) {
        av_log(NULL, AV_LOG_ERROR, "DecodeThread::Init() Failed\n");
    }
    ret = audio_decode_thread->Start();
    if (ret < 0) {
        av_log(NULL, AV_LOG_ERROR, "DecodeThread::Start() Failed\n");
    }
    auto *video_decode_thread = new DecodeThread(&video_packet_queue, &video_frame_queue);
    ret = video_decode_thread->Init(demux_thread->VideoCodecParameters());
    if (ret < 0) {
        av_log(NULL, AV_LOG_ERROR, "DecodeThread::Init() Failed\n");
    }
    ret = video_decode_thread->Start();
    if (ret < 0) {
        av_log(NULL, AV_LOG_ERROR, "DecodeThread::Start() Failed\n");
    }

    SDL_AudioSpec audio_spec = {};
//    memset(&audio_spec, 0, sizeof(SDL_AudioSpec));
    audio_spec.channels = demux_thread->AudioCodecParameters()->ch_layout.nb_channels;
    audio_spec.freq = demux_thread->AudioCodecParameters()->sample_rate;
    audio_spec.format = SDL_AUDIO_S32;

    auto *audio_output = new AudioOutput(audio_spec, &audio_frame_queue);
    ret = audio_output->Init();

    if (ret < 0) {
        av_log(NULL, AV_LOG_ERROR, "AudioOutput::Init() Failed\n");
        return -1;
    }
    audio_output->PlayAudio();
    auto *video_output = new VideoOutput(&video_frame_queue,
                                         demux_thread->VideoCodecParameters()->width,
                                         demux_thread->VideoCodecParameters()->height);
    // VideoOutput *video_output = new VideoOutput(&video_frame_queue, 480, 300);
    ret = video_output->Init();
    if (ret < 0) {
        av_log(NULL, AV_LOG_ERROR, "VideoOutput::Init() Failed\n");
        return -1;
    }
    video_output->MainLoop();
    delete video_output;
    demux_thread->Stop();
    av_log(NULL, AV_LOG_INFO, "DemuxThread::Stop()\n");
    delete demux_thread;
    audio_decode_thread->Stop();
    av_log(NULL, AV_LOG_INFO, "audioThread::Stop()\n");
    delete audio_decode_thread;
    video_decode_thread->Stop();
    av_log(NULL, AV_LOG_INFO, "videoThread::Stop()\n");
    delete video_decode_thread;
    return 0;
}
